﻿using Google.Protobuf;
using MP_Game.Protos.V1;
using System;
using System.Collections.Generic;
using System.Net.Sockets;

namespace MP_Network
{
    public class ServerBase
    {
        // 客户都类型
        public CliType _clientType;
        public Action<CmdId, ByteString> OnReceiveMsg;
        protected Dictionary<CmdId, IContainer> _cmdDic = new();

        protected Socket _socket;
        private byte[] _buffer = new byte[1024 * 4];

        // 连接状态
        protected ConnState _connState;
        // 作为服务端时拿到的客户端引用
        public NetClient _client;

        protected void BeginReceive()
        {
            _socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, OnReceiveCB, null);
        }

        private void OnReceiveCB(IAsyncResult ar)
        {
            try
            {
                int len = _socket.EndReceive(ar);
                if (len > 0)
                {
                    while (true)
                    {
                        ushort msgLen = BitConverter.ToUInt16(_buffer, 0);
                        if (len >= msgLen + 2)
                        {
                            byte[] data = NetUtils.Instance.ParseData(_buffer, msgLen);
                            if (data != null)
                            {
                                GamePacket packet = GamePacket.Parser.ParseFrom(data);
                                LogMsg.Info("Get Packet::" + packet.ToString());
                                HandleCommand(packet);
                            }
                            len -= msgLen + 2;
                            // 粘包处理
                            if (len > 0)
                            {
                                Buffer.BlockCopy(_buffer, msgLen + 2, _buffer, 0, len);
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    BeginReceive();
                }
                else
                {
                    Disconnect();
                }
            }
            catch (Exception ex)
            {
                Disconnect();
                LogMsg.Error("ServerBase::OnReceiveCB::" + ex.Message);
            }

        }



        protected virtual void HandleCommand(GamePacket packet)
        {
        }

        public virtual void Disconnect()
        {
            _connState = ConnState.Disconnected;
            if (_socket != null)
            {
                _socket.Close();
                _socket = null;
            }
        }

        /// <summary>
        /// 向玩家客户端发送消息
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="cmdId"></param>
        /// <param name="data"></param>
        public virtual void SendData(GamePacket packet, int cmdId = -1, ByteString data = null)
        {
            try
            {
                if (cmdId != -1)
                {
                    packet.CmdId = (CmdId)cmdId;
                }
                if (data != null)
                {
                    packet.Data = data;
                }
                LogMsg.Info($"{_socket.RemoteEndPoint}发送了数据::{packet.ToString()}");
                _socket.Send(NetUtils.Instance.MakeData(packet.ToByteArray()));
            }
            catch (Exception ex)
            {
                LogMsg.Error(ex.Message);
            }
        }
    }
}
